package top.mcwebsite.markdown.render

import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInParent
import kotlin.math.roundToInt
import org.intellij.markdown.MarkdownElementTypes
import org.intellij.markdown.MarkdownTokenTypes
import org.intellij.markdown.ast.ASTNode
import org.intellij.markdown.ast.getTextInNode
import top.mcwebsite.markdown.model.MarkdownNode
import top.mcwebsite.markdown.theme.LocalMarkdownTheme
import top.mcwebsite.markdown.theme.MarkdownTheme

object HeadingComponent : MarkdownComponent {

    @Composable
    override fun render(markdownNode: MarkdownNode) {
        val theme = LocalMarkdownTheme.current
        val headingStyle = getDefaultHeadingStyle(markdownNode.node, theme)
        val astNode = getHeadingContent(markdownNode.node)
        MarkdownText(
            markdownNode.content,
            astNode,
            markdownNode.state,
            headingStyle,
            modifier = Modifier
                .padding(theme.blockPadding)
                .onGloballyPositioned {
                    markdownNode.state
                        .addHeaderPosition(
                            astNode.getTextInNode(markdownNode.content).toString().trim(),
                            it.positionInParent().y.roundToInt()
                        )
                }
        )
    }
}

internal fun getDefaultHeadingStyle(astNode: ASTNode, markdownTheme: MarkdownTheme) =
    when (astNode.type) {
        MarkdownElementTypes.ATX_1, MarkdownElementTypes.SETEXT_1 ->
            markdownTheme.heading1Style

        MarkdownElementTypes.ATX_2, MarkdownElementTypes.SETEXT_2 ->
            markdownTheme.heading2Style

        MarkdownElementTypes.ATX_3 ->
            markdownTheme.heading3Style

        MarkdownElementTypes.ATX_4 ->
            markdownTheme.heading4Style

        MarkdownElementTypes.ATX_5 ->
            markdownTheme.heading5Style

        MarkdownElementTypes.ATX_6 ->
            markdownTheme.heading6Style

        else -> throw IllegalArgumentException("Unknown Heading type: ${astNode.type}")
    }

internal fun getHeadingContent(astNode: ASTNode): ASTNode {
    return if (astNode.type == MarkdownElementTypes.SETEXT_1 || astNode.type == MarkdownElementTypes.SETEXT_2) {
        astNode.children.find { it.type == MarkdownTokenTypes.SETEXT_CONTENT }
    } else {
        astNode.children.find { it.type == MarkdownTokenTypes.ATX_CONTENT }
    } ?: throw IllegalArgumentException("Unknown Heading type: ${astNode.type}")
}